package engine.operators.metric;

public class MetricUtils {

	private double[] precomputedCummulativeLogarithm;

	public MetricUtils(int populationSize) {

		assert (populationSize >= 0);

		precomputeCummulativeLogarithms(populationSize + 3);
	}

	private void precomputeCummulativeLogarithms(int n) {

		precomputedCummulativeLogarithm = new double[n + 1];

		double sum = 0;
		precomputedCummulativeLogarithm[0] = 0.0d;

		for (int i = 1; i <= n; i++) {
			sum += Math.log(i);
			precomputedCummulativeLogarithm[i] = sum;
		}
	}

	/**
	 * returns a precomputed cummulative logarithm (log(i)+...+log(j))
	 * 
	 * @param start
	 *          start number
	 * @param end
	 *          end number
	 * @return
	 */
	private double getPrecomputedCummulativeLog(int start, int end) {
		return precomputedCummulativeLogarithm[end]
				- precomputedCummulativeLogarithm[start - 1];
	}

	/**
	 * computes a log of the Gamma function (defined as a factorial of the input
	 * decreased by 1)
	 * 
	 * @param x
	 * @return log of the Gamma(x)
	 */
	public double logGamma(int x) {
		if (x == 1)
			return 0;
		else
			return getPrecomputedCummulativeLog(1, x - 1);
	}
}
